﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Xml.Linq;
using WeiboEx.Models;
using WeiboSharp;
using WeiboSharp.Authenticators;
using WeiboSharp.Authenticators.OAuth;
using WeiboSharp.Models;
using WeiboSharp.Web;

namespace WeiboEx.Weibo
{
    public class QqWeibo : IWeibo
    {
        private const string BaseUrl = "http://open.t.qq.com/api";
        private const string OAuthUrl = "https://open.t.qq.com/cgi-bin";
        private const string WebSite = "http://t.qq.com/";
        private const string ConsumerKey = "";
        private const string ConsumerSecret = "";


        private OAuth1Authenticator _credentials;
        private WeiboClient _client;
        private XElement _xml;

        public bool IsAuth { get; set; }

        private OAuth1Authenticator Credentials { get { return _credentials ?? new OAuth1Authenticator(); } }

        public QqWeibo()
        {
            OAuthKey = new OAuthModel { ConsumerKey = ConsumerKey, ConsumerSecret = ConsumerSecret };
            _client = new WeiboClient();
        }

        public OAuthModel OAuthKey { get; set; }

        public bool GetRequsetToken()
        {
            _credentials = new OAuth1Authenticator
            {
                SignatureMethod = OAuthSignatureMethod.HmacSha1,
                ParameterHandling = OAuthParameterHandling.UrlOrPostParameters,
                ConsumerKey = ConsumerKey,
                ConsumerSecret = ConsumerSecret,
                Token = OAuthKey.Token,
                TokenSecret = OAuthKey.TokenSecret,
                Verifier = OAuthKey.Verifier,
                Type = OAuthType.RequestToken,
                CallbackUrl = OAuthKey.Callback,
            };
            var request = new WeiboRequest
            {
                Path = "request_token",
            };

            return OAuthRequest(request);
        }

        public bool GetAccessToken(string token, string tokensecret, string verifier)
        {
            OAuthKey.Token = token;
            OAuthKey.TokenSecret = tokensecret;
            OAuthKey.Verifier = verifier;

            _credentials = new OAuth1Authenticator
            {
                SignatureMethod = OAuthSignatureMethod.HmacSha1,
                ParameterHandling = OAuthParameterHandling.UrlOrPostParameters,
                ConsumerKey = ConsumerKey,
                ConsumerSecret = ConsumerSecret,
                Token = OAuthKey.Token,
                TokenSecret = OAuthKey.TokenSecret,
                Verifier = OAuthKey.Verifier,
                Type = OAuthType.AccessToken,
            };

            var request = new WeiboRequest
            {
                Path = "access_token"
            };

            return OAuthRequest(request);
        }

        private bool OAuthRequest(WeiboRequest request)
        {
            _client.BaseUrl = OAuthUrl;
            _client.Credentials = Credentials;
            var response = _client.Excute(request);

            if (response.StatusCode == HttpStatusCode.OK)
            {
                var values = HttpUtility.ParseQueryString(response.Content, Encoding.UTF8);
                OAuthKey.Token = values["oauth_token"];
                OAuthKey.TokenSecret = values["oauth_token_secret"];
                return true;
            }
            return false;
        }

        public virtual string GetAuthorizationUri(OAuthModel oauth, string callback)
        {
            return OAuthUrl + "/authorize?oauth_token=" + oauth.Token + "&oauth_callback=" + callback;
        }

        public WeiboUser User { get; set; }


        void GetUser(XElement xml)
        {
            User = new WeiboUser
            {
                Id = "0",
                ScreenName = xml.Element("nick").Value,
                ProfileImageUrl = xml.Element("head").Value + "/120",
                Url = WebSite + xml.Element("name").Value,
            };
        }

        public bool Auth()
        {
            var request = new WeiboRequest()
            {
                Path = "user/info",
            };
            request.AddParameter("format", "xml");
            if (WebMethodResult(request))
            {
                IsAuth = true;
                GetUser(_xml);
            }
            return IsAuth;
        }

        public bool UpdateProfileImage(string pic)
        {
            var request = new WeiboRequest()
            {
                Path = "user/update_head",
                Method = WebMethod.Post
            };
            request.AddParameter("format", "xml");
            request.AddFile("pic", pic);

            return WebMethodResult(request);
        }

        public bool FollowMe(string userId)
        {
            var request = new WeiboRequest()
            {
                Path = "friends/add",
                Method = WebMethod.Post,
            };
            request.AddParameter("format", "xml");
            request.AddParameter("name", userId);

            return WebMethodResult(request);
        }

        public bool UpdateStatus(string status, out long tweetid)
        {
            var request = new WeiboRequest()
            {
                Path = "t/add",
                Method = WebMethod.Post,
            };
            request.AddParameter("format", "xml");
            request.AddParameter("content", status);
            request.AddParameter("clientip", HttpContext.Current.Request.UserHostAddress);
            request.AddParameter("jing", "");
            request.AddParameter("wei", "");
            var suc = WebMethodResult(request);
            tweetid = 0;
            if (suc)
            {
                tweetid = Convert.ToInt64(_xml.Element("id").Value);
            }
            return suc;
        }

        public bool UploadStatus(string status, string pic, out long tweetid)
        {
            var request = new WeiboRequest()
            {
                Path = "t/add_pic",
                Method = WebMethod.Post
            };
            request.AddParameter("format", "xml");
            request.AddParameter("content", status);
            request.AddParameter("clientip", "192.168.1.1");
            request.AddParameter("jing", "");
            request.AddParameter("wei", "");
            request.AddFile("pic", pic);

            var suc = WebMethodResult(request);
            tweetid = 0;
            if (suc)
            {
                tweetid = Convert.ToInt64(_xml.Element("id").Value);
            }
            return suc;
        }

        public bool Repost(long id, string status, out long retweetid)
        {
            var request = new WeiboRequest()
            {
                Path = "t/re_add",
                Method = WebMethod.Post,
            };
            if (string.IsNullOrWhiteSpace(status))
            {
                status = "转发微博";
            }
            request.AddParameter("format", "xml");
            request.AddParameter("content", status);
            request.AddParameter("clientip", "192.168.1.1");
            request.AddParameter("jing", "");
            request.AddParameter("wei", "");
            request.AddParameter("reid", id.ToString());
            var suc = WebMethodResult(request);
            retweetid = 0;
            if (suc)
            {
                retweetid = Convert.ToInt64(_xml.Element("id").Value);
            }
            return suc;
        }

        public bool UserTimeLine(int count, int page, out IEnumerable<Status> statuses)
        {
            var request = new WeiboRequest()
            {
                Path = "statuses/user_timeline",
                Method = WebMethod.Get,
            };

            request.AddParameter("count", count.ToString());
            request.AddParameter("page", page.ToString());

            bool suc = WebMethodResult(request);
            statuses = new List<Status>();
            if (suc)
            {
                statuses = from status in _xml.Elements("status")
                           select Status.Create(status);
            }
            return suc;
        }

        private bool WebMethodResult(WeiboRequest request)
        {
            try
            {
                _credentials = new OAuth1Authenticator
                {
                    SignatureMethod = OAuthSignatureMethod.HmacSha1,
                    ParameterHandling = OAuthParameterHandling.UrlOrPostParameters,
                    ConsumerKey = ConsumerKey,
                    ConsumerSecret = ConsumerSecret,
                    Token = OAuthKey.Token,
                    TokenSecret = OAuthKey.TokenSecret,
                    Type = OAuthType.ProtectedResource,
                };
                _client.Credentials = Credentials;
                _client.BaseUrl = BaseUrl;
                var response = _client.Excute(request);
                if (response.StatusCode == HttpStatusCode.OK)
                {
                    var xml = XElement.Parse(response.Content);
                    _xml = xml.Element("data");
                    return xml.Element("ret").Value == "0";
                }
            }
            catch (Exception)
            {
                return false;
            }
            return false;
        }
    }
}